package com.i1314i.reportsystem.shiro.realm;

import com.i1314i.reportsystem.mapper.RoleMapper;
import com.i1314i.reportsystem.mapper.UserMapper;
import com.i1314i.reportsystem.po.Role;
import com.i1314i.reportsystem.po.User;
import com.i1314i.reportsystem.service.user.UserService;
import com.i1314i.reportsystem.shiro.token.IToken;
import com.i1314i.reportsystem.utils.jedisUtils.IJedisClient;
import com.i1314i.reportsystem.utils.redisToken.TokenUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *
 * @Author 平行时空
 * @Description 自定义 TokenRealm
 * @created 2018-09-16 22:38
 */
@Component
public class CustomRealm extends AuthorizingRealm {
    private Logger logger= LoggerFactory.getLogger(CustomRealm.class);
    @Autowired
    private  UserService userService;
    @Autowired
    private IJedisClient jedisClient;

    /**
     * 必须重写此方法，不然会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof IToken;
    }

    /**
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("————身份认证方法————");
        String token = (String) authenticationToken.getCredentials();

        if (token == null || !TokenUtils.verify(token)) {
            throw new AuthenticationException("token认证失败！");
        }
        User user=TokenUtils.getToken(User.class,token);

        if (user == null) {
            throw new AuthenticationException("该用户不存在！");
        }

        if(user.getUsername()==null){
            throw new AuthenticationException("token认证失败！");
        }
        if (user.getStatus() == 0) {
            throw new AuthenticationException("该用户已被封号！");
        }


        try{
            if(jedisClient.ttl(token)<60*10){
                jedisClient.expire(token,60*60);
            }
        }catch (Exception e){
            logger.info("token延期失败:"+token);
        }


        /* 数据库 查询部分 为减小数据库压力暂时只用缓存
        if(user.getUsername()==null){
            throw new AuthenticationException("token认证失败！");
        }

        User usersql=userService.selectUserByUserName(user.getUsername());

        if (usersql == null) {
            throw new AuthenticationException("该用户不存在！");
        }

        if (usersql.getStatus() == 0) {
            throw new AuthenticationException("该用户已被封号！");
        }

        */
        return new SimpleAuthenticationInfo(token, token, "MyRealm");
    }



    /**
     * 只有当需要检测用户权限的时候才会调用此方法，例如checkRole,checkPermission之类的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("————权限认证————");

        User user=TokenUtils.getToken(User.class,principals.toString());
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获得该用户角色
        String role =user.getRole().getRole();
        //每个角色拥有默认的权限
        String rolePermission = user.getRole().getPermission();
        //每个用户可以设置新的权限
        List<Role>roleList=user.getRoleList();
        Set<String> roleSet = new HashSet<>();
        Set<String> permissionSet = new HashSet<>();
        //需要将 role, permission 封装到 Set 作为 info.setRoles(), info.setStringPermissions() 的参数
        roleSet.add(role);
        permissionSet.add(rolePermission);
        for (Role rolestring:roleList
             ) {
        // roleSet.add(rolestring.getRole());
            permissionSet.add(rolestring.getPermission());
        }

        //设置该用户拥有的角色和权限
        info.setRoles(roleSet);
        info.setStringPermissions(permissionSet);
        return info;
    }
}
